use core::usize;

use crate::fs::block::BLOCK_SIZE;
use alloc::{
    string::{String, ToString},
    sync::Arc,
    vec,
    vec::Vec,
};
pub struct BIOSParameterBlock {
    pub(crate) bytes_per_sector: u16,
    pub(crate) sectors_per_cluster: u8,
    pub(crate) reserved_sector_num: u16,
    pub(crate) fat_num: u8,
    pub(crate) sector_per_fat: u32,
    pub(crate) root_cluster_idx: u32,
    pub(crate) fs_type: [u8; 8],

    // 这里自定义一些会用到的字段
    // 物理设备的最小读取单元可能与
    // 系统定义的最小单元Block 大小不相同
    // 所以需要做一下转换
    pub(crate) blocks_per_sector: usize,
    pub(crate) blocks_offset_to_data: usize,
    pub(crate) blocks_per_cluster: usize,
}
impl BIOSParameterBlock {
    pub fn build(first_sector: &[u8; BLOCK_SIZE]) -> Self {
        //println!("first sector");
        //println!("{:?}", first_sector);
        let bytes_per_sector = u16::from_le_bytes([first_sector[11], first_sector[12]]);
        //println!("here1");
        //assert!(1 == 2, "wtf");
        if bytes_per_sector as usize % BLOCK_SIZE != 0 {
            println!(
                "{}-{} disk size comflict, os minimal R&W size is {}, device minimal R&W size is {}",
                file!(), line!(), BLOCK_SIZE, bytes_per_sector
            );
            // 为什么 make 不打印panic信息
            panic!("wtf");
        }
        let sectors_per_cluster = first_sector[13];
        let reserved_sector_num = u16::from_le_bytes([first_sector[14], first_sector[15]]);
        let fat_num = first_sector[16];
        let sector_per_fat = u32::from_le_bytes([
            first_sector[36],
            first_sector[37],
            first_sector[38],
            first_sector[39],
        ]);
        let blocks_per_sector = bytes_per_sector as usize / BLOCK_SIZE;
        BIOSParameterBlock {
            bytes_per_sector,
            sectors_per_cluster,
            reserved_sector_num,
            fat_num,
            sector_per_fat,
            root_cluster_idx: u32::from_le_bytes([
                first_sector[44],
                first_sector[45],
                first_sector[46],
                first_sector[47],
            ]),
            fs_type: [
                first_sector[82],
                first_sector[83],
                first_sector[84],
                first_sector[85],
                first_sector[86],
                first_sector[87],
                first_sector[88],
                first_sector[89],
            ],
            blocks_per_sector,
            blocks_offset_to_data: (reserved_sector_num as usize
                + fat_num as usize * sector_per_fat as usize)
                * blocks_per_sector,
            blocks_per_cluster: sectors_per_cluster as usize * blocks_per_sector,
        }
    }

    pub fn is_valid(&self) -> bool {
        let ft = String::from_utf8_lossy(&self.fs_type)
            .trim_end_matches(char::from(0x20))
            .to_string();
        print!("file type is: {}\n", ft);
        self.fs_type == *b"FAT32   "
    }
}
